package com.lagou.session;

import com.lagou.bean.Configuration;
import com.lagou.bean.MapperStatement;

import java.lang.reflect.*;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;

public class DefaultSqlSession implements SqlSession {
    private Configuration configuration;
    private Executor executor = new SimpleExecutor();
    public DefaultSqlSession(Configuration conf) {
        this.configuration = conf;
    }
    @Override
    public <E> List<E> selectList(String statementId, Object[] params) throws Exception {
        MapperStatement stmt = configuration.getMappers().get(statementId);
        return executor.query(configuration, stmt, params);
    }

    @Override
    public <E> E selectOne(String statementId, Object[] params) throws Exception {
        List<E> result = this.selectList(statementId, params);
        if (result.size()>1) {
            throw new RuntimeException("返回结果过多");
        }
        if (result.isEmpty()) {
            return null;
        }
        return result.get(0);
    }

    @Override
    public void close() throws SQLException {
        this.executor.close();
    }

    @Override
    public <E> E getMapper(Class<?> mapperClass) {
       Object o = Proxy.newProxyInstance(mapperClass.getClassLoader(), new Class[] {mapperClass},
               new InvocationHandler() {
            @Override
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                String methodName = method.getName();
                String clz = method.getDeclaringClass().getName();
                String key = clz + "." + methodName;
                //MapperStatement stmt = configuration.getMappers().get(key);
                Type type = method.getGenericReturnType();
                if (type instanceof ParameterizedType) {
                    return selectList(key, objects);
                }
                return selectOne(key, objects);
            }
        });
        return (E)o;
    }

    @Override
    public int update(String statementId, Object... params) throws  Exception {
        MapperStatement stmt = configuration.getMappers().get(statementId);
        return this.executor.update(configuration, stmt, params);
    }
}
